﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace UmlControlLibrary
{
    public enum UmlModifier { _private=1, _protected=2, _public=4, _internal=8, _abstract=16, _virtual=32, _final=64, _static=128, _readonly=256 }

    public class UmlModifierItem
    {
        private static bool HasFlag(MethodAttributes attr, MethodAttributes flag)
        {
            return ((attr & flag) == flag);
        }

        private static bool HasFlag(FieldAttributes attr, FieldAttributes flag)
        {
            return ((attr & flag) == flag);
        }


        /*
         * 
         * public static TypeAttributes TypeAttr (int mod_flags, bool is_toplevel)
		{
			TypeAttributes t = 0;
        public = typeattributes & public
        private = typeattributes & notpublic
        
			if (is_toplevel){
				if ((mod_flags & PUBLIC) != 0)
					t |= TypeAttributes.Public;
				if ((mod_flags & PRIVATE) != 0)
					t |= TypeAttributes.NotPublic;
			} else {
				if ((mod_flags & PUBLIC) != 0)
					t |= TypeAttributes.NestedPublic;
				if ((mod_flags & PRIVATE) != 0)
					t |= TypeAttributes.NestedPrivate;
				if ((mod_flags & PROTECTED) != 0 && (mod_flags & INTERNAL) != 0)
					t |= TypeAttributes.NestedFamORAssem;
				if ((mod_flags & PROTECTED) != 0)
					t |= TypeAttributes.NestedFamily;
				if ((mod_flags & INTERNAL) != 0)
					t |= TypeAttributes.NestedAssembly;
			}
			
			if ((mod_flags & SEALED) != 0)
				t |= TypeAttributes.Sealed;
			if ((mod_flags & ABSTRACT) != 0)
				t |= TypeAttributes.Abstract;

			return t;
		}

		public static FieldAttributes FieldAttr (int mod_flags)
		{
			FieldAttributes fa = 0;

			if ((mod_flags & PUBLIC) != 0)
				fa |= FieldAttributes.Public;
			if ((mod_flags & PRIVATE) != 0)
				fa |= FieldAttributes.Private;
			if ((mod_flags & PROTECTED) != 0){
				if ((mod_flags & INTERNAL) != 0)
					fa |= FieldAttributes.FamORAssem;
				else 
					fa |= FieldAttributes.Family;
			} else {
				if ((mod_flags & INTERNAL) != 0)
					fa |= FieldAttributes.Assembly;
			}
			
			if ((mod_flags & STATIC) != 0)
				fa |= FieldAttributes.Static;
			if ((mod_flags & READONLY) != 0)
				fa |= FieldAttributes.InitOnly;

			return fa;
		}

		public static MethodAttributes MethodAttr (int mod_flags)
		{
			MethodAttributes ma = MethodAttributes.HideBySig;
          
         * 
         * public = public
         * private = private
         * protected = family
         * internal = assembly

			if ((mod_flags & PUBLIC) != 0)
				fa |= FieldAttributes.Public;
			if ((mod_flags & PRIVATE) != 0)
				fa |= FieldAttributes.Private;
			if ((mod_flags & PROTECTED) != 0){
				if ((mod_flags & INTERNAL) != 0)
					fa |= FieldAttributes.FamORAssem;
				else 
					fa |= FieldAttributes.Family;
			} else {
				if ((mod_flags & INTERNAL) != 0)
					fa |= FieldAttributes.Assembly;
			}
         * if ((mod_flags & PUBLIC) != 0)
				ma |= MethodAttributes.Public;
			if ((mod_flags & PRIVATE) != 0)
				ma |= MethodAttributes.Private;
			if ((mod_flags & PROTECTED) != 0){
				if ((mod_flags & INTERNAL) != 0)
					ma |= MethodAttributes.FamORAssem;
				else 
					ma |= MethodAttributes.Family;
			} else {
				if ((mod_flags & INTERNAL) != 0)
					ma |= MethodAttributes.Assembly;
			}

			if ((mod_flags & STATIC) != 0)
				ma |= MethodAttributes.Static;
			if ((mod_flags & ABSTRACT) != 0){
				ma |= MethodAttributes.Abstract | MethodAttributes.Virtual;
			}
			if ((mod_flags & SEALED) != 0)
				ma |= MethodAttributes.Final;

			if ((mod_flags & VIRTUAL) != 0)
				ma |= MethodAttributes.Virtual;

			if ((mod_flags & OVERRIDE) != 0)
				ma |= MethodAttributes.Virtual;
			else {
				if ((ma & MethodAttributes.Virtual) != 0)
					ma |= MethodAttributes.NewSlot;
			}
			
			return ma;
		}*/

        public static UmlModifier GetUmlModifiers(MethodAttributes methodAttributes)
        {
            UmlModifier modifiers = new UmlModifier();
            if (HasFlag(methodAttributes, MethodAttributes.FamORAssem))
                modifiers |= UmlModifier._protected | UmlModifier._internal;
            else
            {
                if (HasFlag(methodAttributes, MethodAttributes.Public)) modifiers |= UmlModifier._public;
                else if (HasFlag(methodAttributes, MethodAttributes.Family)) modifiers |= UmlModifier._protected;
                else if (HasFlag(methodAttributes, MethodAttributes.Assembly)) modifiers |= UmlModifier._internal;
                else if (HasFlag(methodAttributes, MethodAttributes.Private)) modifiers |= UmlModifier._private;
            }

            if (HasFlag(methodAttributes, MethodAttributes.Abstract)) modifiers |= UmlModifier._abstract;
            if (HasFlag(methodAttributes, MethodAttributes.Final)) modifiers |= UmlModifier._final;
            if (HasFlag(methodAttributes, MethodAttributes.Static)) modifiers |= UmlModifier._static;
            if (HasFlag(methodAttributes, MethodAttributes.Virtual)) modifiers |= UmlModifier._virtual;

            return modifiers;
        }

        public static UmlModifier GetUmlModifiers(FieldAttributes fieldAttributes)
        {
            UmlModifier modifiers = new UmlModifier();
            if (HasFlag(fieldAttributes, FieldAttributes.FamORAssem))
                modifiers |= UmlModifier._protected | UmlModifier._internal;
            else
            {
                if (HasFlag(fieldAttributes, FieldAttributes.Public)) modifiers |= UmlModifier._public;
                else if (HasFlag(fieldAttributes, FieldAttributes.Family)) modifiers |= UmlModifier._protected;
                else if (HasFlag(fieldAttributes, FieldAttributes.Assembly)) modifiers |= UmlModifier._internal;
                else if (HasFlag(fieldAttributes, FieldAttributes.Private)) modifiers |= UmlModifier._private;
            }

            if (HasFlag(fieldAttributes, FieldAttributes.Static)) modifiers |= UmlModifier._static;
            if (HasFlag(fieldAttributes, FieldAttributes.InitOnly)) modifiers |= UmlModifier._virtual;

            return modifiers;
        }


        public UmlModifier Modifier
        {
            get;
            set;
        }
        public string Label
        {
            get;
            set;
        }
        public UmlModifierItem(UmlModifier modifier, string label)
        {
            Modifier = modifier;
            Label = label;
        }

        private static List<UmlModifierItem> _propertyModifiers = null;
        public static List<UmlModifierItem> GetPropertyModifiers()
        {
            if (_propertyModifiers == null)
            {
                _propertyModifiers = new List<UmlModifierItem>();
                _propertyModifiers.Add(new UmlModifierItem(UmlModifier._private, "Private"));
                _propertyModifiers.Add(new UmlModifierItem(UmlModifier._public, "Public"));
                _propertyModifiers.Add(new UmlModifierItem(UmlModifier._protected, "Protected"));
            }
            return _propertyModifiers;
        }
    }
}
